package main

import (
	"fmt"
	"time"
	"strings"
	"context"
	"errors"
	"encoding/json"

	"go.etcd.io/etcd/clientv3"
	log "github.com/sirupsen/logrus"
)

var (
	etcdAddr = "127.0.0.1:2379"
	etcdPrefix = "perfix"
)

type Book struct {
	Auth string
	Test string
}

func newClient() *clientv3.Client {
	parsed_db_addr := strings.Split(etcdAddr, ",")
	client, err := clientv3.New(clientv3.Config{
		Endpoints:   parsed_db_addr,
		DialTimeout: 5 * time.Second,
	})
	if err != nil {
		log.Error("connect failed, err :", err)
	}
	return client
}


func SetKey(key string,  arg interface{}) error {
	cli := newClient()
	kvapi := clientv3.NewKV(cli)
	var (
		err  error
		temp []byte
		data string
	)
	key = fmt.Sprintf("/%s/%s", etcdPrefix, key)
    value, ok := arg.(string)
    if !ok {
		temp, err = json.Marshal(arg)
		if err != nil {
			return errors.New("Etcd data error.")
		}
		data = string(temp)
	} else {
		data = value
	}
	_, err = kvapi.Put(context.Background(), key, data, clientv3.WithPrevKV())
	if err != nil {
		return errors.New("Etcd insert data error.")
	}
	return nil
}


func GetKey(key string, arg interface{})  interface{} {
	cli := newClient()
	kvapi := clientv3.NewKV(cli)
	key = fmt.Sprintf("/%s/%s",etcdPrefix, key)
	resp, err := kvapi.Get(context.TODO(), key)
	if err != nil {
		return errors.New("Etcd request data error.")
	}
	_, ok := arg.(bool)
	if !ok {
		result := arg
		json.Unmarshal([]byte(string(resp.Kvs[0].Value)), result)
		return result
	}
	return string(resp.Kvs[0].Value)
}


func main() {
	SetKey("book",Book{Auth: "zhangsan", Test: "lisi"})
	res := GetKey("book", &Book{})
	te, ok := res.(*Book)
	fmt.Println(ok)
	fmt.Println(te.Auth)
	fmt.Println(te.Test)

	SetKey("strs","demo")
	res1 := GetKey("strs", false)
	fmt.Println(res1)


}